package cn.ydxiaoshuai.pdf;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author 小帅丶
 * @className PDFToImageSample
 * @Description PDF转图片
 * @Date 2021-07-08-11:50
 **/
@Slf4j
public class PDFToImageUtil {
    /** PDF格式 */
    public static final String SUPPORT_FILE = "PDF";
    /** 保存图片的格式 */
    public static final String IMAGE_SUFFIX = "JPG";

    /**
     * @Author 小帅丶
     * @Description PDF转图片
     * @Date  2021-07-08 11:52
     * @param filePath - PDF 文件路径
     * @return java.util.List<java.lang.String>
     **/
    public static List<String> pdfToImagePath(String filePath) {
        List<String> list = new ArrayList<>();
        //获取去除后缀的文件路径
        String fileDirectory = filePath.substring(0,
                filePath.lastIndexOf("."));
        String imagePath;
        File file = new File(filePath);
        try {
            File f = new File(fileDirectory);
            if (!f.exists()) {
                f.mkdir();
            }
            PDDocument doc = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            for (int i = 0; i < pageCount; i++) {
                //第二个参数越大生成图片分辨率越高，转换时间也就越长
                BufferedImage image = renderer.renderImage(i, 1.25f);
                //BufferedImage image = renderer.renderImageWithDPI(i,300);
                imagePath = fileDirectory + "/" + i + "."+IMAGE_SUFFIX.toLowerCase();
                ImageIO.write(image,
                        IMAGE_SUFFIX.toLowerCase(),
                        new File(imagePath));
                list.add(imagePath);
            }
        } catch (IOException e) {
            log.info("PDF转图片 出错了{}",e.getMessage());
        }
        return list;
    }

    /**
     * @Author 小帅丶
     * @Description PDF转图片BufferedImage
     * @Date  2022年5月12日
     * @param fileByte - PDF fileByte
     * @param dpi - 分辨率
     * @return java.util.List<BufferedImage>
     **/
    public static List<BufferedImage> pdfToBufferedImage(byte[] fileByte,float dpi) {
        if(dpi<=0){
            dpi = 300;
        }
        List<BufferedImage> list = new ArrayList<>();
        Set<String> fontSet = new HashSet<>();
        try {
            PDDocument doc = PDDocument.load(fileByte);
            PDPageTree pages = doc.getDocumentCatalog().getPages();
            PDResources resources = pages.get(0).getResources();
            for (COSName fontName : resources.getFontNames()) {
                PDFont font = resources.getFont(fontName);
                fontSet.add(font.getFontDescriptor().getFontName());
            }
            String fontNames = String.join(",", fontSet);
            System.out.println("PDF中使用的字体-------"+fontNames);
            int pageCount = doc.getNumberOfPages();
            PDFRenderer renderer = new PDFRenderer(doc);
            for (int i = 0; i < pageCount; i++) {
                BufferedImage image = renderer.renderImageWithDPI(i,dpi);
                list.add(image);
            }
            doc.close();
        } catch (IOException e) {
            log.info("PDF转图片 出错了{}",e.getMessage());
        }
        return list;
    }

    /**
     * @Author 小帅丶
     * @Description PDF转图片BufferedImage
     * @Date  2022年5月12日
     * @param filePath - PDF 文件路径
     * @param dpi
     * @return java.util.List<BufferedImage>
     **/
    public static List<BufferedImage> pdfToBufferedImage(String filePath,float dpi) {
        byte[] bytes = FileUtil.readBytes(filePath);
        return pdfToBufferedImage(bytes,dpi);
    }

    /***
     * 图片对象转字节
     *
     * @param images  图片对象
     * @return List<byte[]>
     */
    public static List<byte[]> imageToByte(List<BufferedImage> images){
        List<byte[]> list = new ArrayList<>();
        if (ObjectUtil.isEmpty(images)){
            return list;
        }
        try(
                ByteArrayOutputStream os = new ByteArrayOutputStream();
        ) {
            for (BufferedImage image : images) {
                ImageIO.write(image, "jpg", os);
                //base64编码
                list.add(os.toByteArray());
                // 重置
                os.reset();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

    /***
     * 图片对象转换base64
     *
     * @param images  图片对象
     * @return 图片base64
     */
    public static List<String> imageToBase64(List<BufferedImage> images){
        List<String> list = new ArrayList<>();
        if (ObjectUtil.isEmpty(images)){
            return list;
        }
        try(
                ByteArrayOutputStream os = new ByteArrayOutputStream();
        ) {
            for (BufferedImage image : images) {
                ImageIO.write(image, "jpg", os);
                byte[] dataList = os.toByteArray();
                //base64编码
                list.add(Base64Encoder.encode(dataList));
                // 重置
                os.reset();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

    /***
     * 图片对象转字节
     *
     * @param images  图片对象
     * @return List<byte[]>
     */
    public static byte[] imageToByte(BufferedImage images){
        try(
                ByteArrayOutputStream os = new ByteArrayOutputStream();
        ) {
            ImageIO.write(images, "jpg", os);
            return os.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    /**
     * 竖直合并图片
     *
     * @param images 图片对象
     * @return BufferedImage
     */
    public static BufferedImage mergePic(List<BufferedImage> images) {
        //最终图片宽、高，所有图片中最宽
        int desWidth = 0, desHeight = 0, maxWidth = 0;
        //新图片
        BufferedImage desImage;
        //没有图片返回null
        if (images.isEmpty()) {
            return null;
        }
        if(images.size() == 1){
            return images.get(0);
        }
        //合并图片
        //计算合成的图片长高
        for (BufferedImage img : images) {
            desWidth = img.getWidth();
            //获取最宽的图片
            if (desWidth > maxWidth) {
                maxWidth = desWidth;
            }
            desHeight += img.getHeight();
        }
        desWidth = maxWidth;
        //创建新图片
        desImage = new BufferedImage(desWidth, desHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = desImage.createGraphics();
        //合并子图到新图片
        //像素点起始x,y坐标
        int w_x = 0, h_y = 0;
        for (BufferedImage img : images) {
            int width = img.getWidth();
            int height = img.getHeight();
            graphics.drawImage(img, 0, h_y, null);
            w_x += width;
            h_y += height;
        }
        return desImage;
    }
}
